<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    function isObject(target) {
      return typeof target === 'object' && typeof target !== 'null'
    }
    // function cloneDeep(target) {
    //   const cache = new WeakMap()
    //   function run(obj) {
    //     if(isObject(obj)){

    //       if( obj instanceof Date ) return new Date(obj) 
    //       if( obj instanceof RegExp ) return new RegExp(obj) 

    //       if(cache.has(obj)) return cache.get(obj)

    //       const res = Array.isArray(obj) ? [] : {}
    //       cache.set(obj, res)
    //       for(let i of Reflect.ownKeys(obj)) {
    //         if( obj.hasOwnProperty(i) ) {
    //           res[i] = isObject(obj[i]) ? run(obj[i]) : obj[i]
    //         }
    //       }
    //       return res
    //     }else{
    //       return obj
    //     }
    //   }
    //   return run(target)
    // }
    
    // function cloneDeep( target ) {
    //   const cache = new WeakMap()
    //   function run(target) {
    //     if(!isObject(target)) return target
    //     if(cache.has(target)) return target
    //     const ret = Array.isArray(target) ? [] : {}
    //     cache.set(target, ret)
    //     for(let i in target) {
    //       if(target.hasOwnProperty(i)) {
    //         ret[i] = run(target[i])
    //       }
    //     }
    //     return ret
    //   }
    //   const result = run(target)
    //   return result
    // }
    
    function cloneDeep(target) {
      const cache = new WeakMap()
      function run(target) {
        if(!isObject(target)) return target
        if(cache.has(target)) return target
        if(target instanceof Date) return new Date(target)
        if(target instanceof RegExp) return new RegExp(target)
        const ret = Array.isArray(target) ? [] : {}
        cache.set(target, ret)
        for( let i in target) {
          if(target.hasOwnProperty(i)) {
            ret[i] = run(target[i])
          }
        }

        return ret
      }
      return run(target)
    }
    const x1 = {a: {b: 1,}, sym: Symbol(1)}
    x1.c = x1
    const x2 = cloneDeep(x1)
    x2.a.b = 100
    console.log( x2)
  </script>
</body>
</html>